package com.kuangstudy.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author renyitong
 * @version 1.0.0
 * @createTime 2023年09月15日
 * @Description 完成对bean调用次数的统计
 */
@Aspect
@Component
@Slf4j
public class MethodCallCountAspect {

    private Map<String, AtomicInteger> normalMethodCallCountMap = new ConcurrentHashMap<>();
    private Map<String, AtomicInteger> exMethodCallCountMap = new ConcurrentHashMap<>();
    private Map<String, AtomicInteger> anyMethodCallCountMap = new ConcurrentHashMap<>();

    /**
     * 定义切入点
     */
    @Pointcut("@annotation(com.kuangstudy.anno.MethodCallCount)")
    public void pointcut() {
    }

    /**
     * 定义通知和连接点
     */
    @Around("pointcut()")
    public Object aroundCount(ProceedingJoinPoint joinPoint) {
        // 1：获取方法的签名作为key
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        String className = method.getDeclaringClass().getName();
        String methodName = method.getName();
        String realName = className + "." + methodName;
        Object result = null;
        try {
            result = joinPoint.proceed();
            AtomicInteger counter = normalMethodCallCountMap.computeIfAbsent(realName, k -> new AtomicInteger(0));
            int i = counter.incrementAndGet();
            log.info("调用方法【正常】的次数为：" + i);
            return result;
        } catch (Throwable ex) {
            log.error("afterCount ex: {}", ex);
            AtomicInteger counter = exMethodCallCountMap.computeIfAbsent(realName, k -> new AtomicInteger(0));
            int i = counter.incrementAndGet();
            log.info("调用方法【异常】的次数为：" + i);
        } finally {
            // 计数器+1
            AtomicInteger counter = anyMethodCallCountMap.computeIfAbsent(realName, k -> new AtomicInteger(0));
            int i = counter.incrementAndGet();
            log.info("调用方法【无论正常还是异常】的次数为：" + i);
        }
        return result;
    }

    public int getNormalMethodCallCountNumber(String methodName) {
        AtomicInteger counter = normalMethodCallCountMap.get(methodName);
        return (counter != null) ? counter.get() : 0;
    }

    public int getAnyMethodCallCountNumber(String methodName) {
        AtomicInteger counter = anyMethodCallCountMap.get(methodName);
        return (counter != null) ? counter.get() : 0;
    }


    public int getExMethodCallCountNumber(String methodName) {
        AtomicInteger counter = exMethodCallCountMap.get(methodName);
        return (counter != null) ? counter.get() : 0;
    }


}
